/*
 * Copyright (c) 2011 , Edgar Poce, All rights reserved.
 *
 * Author: Edgar Poce
 *
 * Use, modification and distribution are subject to the "New BSD License"
 * as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
 */
package com.newen.mojo.protobuf4as3;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.logging.Log;

public class AsCodeGenerator {
	/*
	 * NOTES: protoc must be accessible in the path as a system variable (not
	 * user specific)
	 */
	private final static String NAME = "protoc-gen-as3";

	private final Log logger; 

	private final File folder;

	private File pluginBatch;

	private final Artifact compilerArtifact;

	private final Artifact protobufArtifact;

	public AsCodeGenerator(File parent, Artifact compiler, Artifact protobuf, Log logger) {
		super();
		this.folder = new File(parent, NAME + "-" + System.currentTimeMillis());
		this.compilerArtifact = compiler;
		this.protobufArtifact = protobuf;
		this.logger = logger;
	}

	public void init() throws IOException {
		this.folder.mkdir();
		this.copyArtifact(this.compilerArtifact);
		this.copyArtifact(this.protobufArtifact);
		this.pluginBatch = this.createPluginBatch();
	}

	private void copyArtifact(Artifact artifact) throws IOException {
		File from = artifact.getFile();
		File to = new File(this.folder, from.getName());
		FileUtils.copyFile(from, to);
	}

	File createPluginBatch() throws IOException {
		File batch = new File(this.folder, NAME + ".bat");
		logger.info("Created batch: " + batch.getCanonicalPath());
		StringBuilder sb = new StringBuilder();
		sb.append(getBatchHeader());
		sb.append("cd ");
		sb.append(this.folder.getCanonicalPath());
		sb.append("\n");
		sb.append("java -jar ");
		sb.append(compilerArtifact.getFile().getName());
		FileWriter writer = new FileWriter(batch, false);
		logger.info("Created plugin batch: " + batch.getCanonicalPath());
		logger.debug(sb.toString());
		try {
			IOUtils.write(sb.toString(), writer);
		} finally {
			IOUtils.closeQuietly(writer);
		}
		batch.setExecutable(true, false);
		return batch;
	}

	File createProtoBatch(File output, File proto) throws IOException {
		File batch = new File(this.folder, "proto.bat");
		batch.createNewFile();
		StringBuilder sb = new StringBuilder();
		sb.append(getBatchHeader());
		sb.append("cd ");
		sb.append(proto.getParentFile().getCanonicalPath());
		sb.append("\n");
		sb.append("protoc");
		sb.append(" --plugin=\"protoc-gen-as3=");
		sb.append(this.pluginBatch.getCanonicalPath());
		sb.append("\" --as3_out=\"");
		sb.append(output.getCanonicalPath());
		sb.append("\" ");
		sb.append(proto.getName());
		logger.info("Created proto batch: " + batch.getCanonicalPath());
		logger.debug(sb.toString());
		FileUtils.write(batch, sb.toString());
		batch.setExecutable(true, false);
		return batch;
	}
	
	static String getBatchHeader() {
		if (System.getProperty("os.name").toLowerCase().contains("win")) {
			return "@Echo off\n"; 
		} else {
			return "#!/bin/bash\n";
		}
	}

	public void compileProto(File output, File proto) throws IOException,
			InterruptedException {
		File file = this.createProtoBatch(output, proto);
		ProcessBuilder builder = new ProcessBuilder(file.getCanonicalPath(),
				"dir");
		final Process process = builder.start();
		BufferedReader error = new BufferedReader(new InputStreamReader(
				process.getErrorStream()));
		log(error);
		process.waitFor();
	}

	private void log(BufferedReader br) throws IOException {
		String line;
		while ((line = br.readLine()) != null) {
			logger.info(line);
		}
		IOUtils.closeQuietly(br);
	}

	public void clean() {
		try {
			FileUtils.deleteDirectory(this.folder);
		} catch (IOException e) {
			logger.error("unable to delete tmp directory "
					+ this.folder.getName());
		}
	}

	@Override
	public String toString() {
		try {
			return "AsCodeGenerator [folder=" + folder.getCanonicalPath() + "]";
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

}
